<?php
/**
 * 清理未使用年假
 * @author 吕嗣江
 *
 */
apf_require_class('Oa_Job_Attendance_Abstract');
apf_require_class("Tools_Tools");
class Oa_Job_Attendance_ClearUnusedVocation extends Oa_Job_Attendance_Abstract{

    private $how_many_users_per_time = 10;                //每次处理用户的个数
    private $start_user_id = 0;                                    //每次查询用户的开始id
    private $cleared_user = '';                                    //最终被清理年假的所有用户
    private $year;                                                    //当前年
    private $db_adapt = 'attendance_master';                //跑job用master，不用slave

    public function __construct(){//初始化
        parent::__construct();
        $this->year = date( 'Y' );
    }


    /**
     * 清理年假
     * @param unknown_type $param
     */
    public function run( $param ){
        if( $param == 'roll_back' ){
            $this->roll_back();//job执行失败时回滚数据
            die;
        }elseif( $param !== '' && $param != 'test' ){
            $this->log('参数不正确');
            die;
        }
        $this->log( '清理年假开始' );
        $this->log( '每次取出的职员个数：'.$this->how_many_users_per_time );
        $start = date('Y-m-d',mktime(0,0,0,1,0,date( 'Y' )));
        while( TRUE ){
            //分批取得用户
            $users = $this->get_users( $param );
            $this->do_clear( $users, $start );
            if( count($users) < $this->how_many_users_per_time ){ //一旦取出的用户数小于每次应该取出的数量，说明已经读到了表的末尾，退出循环
                $this->log('已经处理完所有职员！');
                break;
            }
        }
        $this->log('所有被清理年假的职员'.$this->cleared_user);
        $this->log( '清理年假结束' );
    }


    /**
     * 当job跑失败的时候运行这个函数，将之前跑job所改变的数据回滚
     */
    private function roll_back(){
        $cleared_user_last_time = $this->get_cleared_user_last_time();//上一次已经清理成功的职员
        $success = $this->do_roll_back( $cleared_user_last_time );
        $success ? $this->log( '年假回滚成功！' ) : $this->log( '年假回滚失败！' ) ;
    }


    /**
     * 分批取出用户
     * @return array 用户数组
     */
    private function get_users( $param ){
        $this->log( '本次取职员的起始id '.$this->start_user_id );
        $sql = 'SELECT user_id,name,code,enter_date FROM user_info WHERE job_status = \'在职\' AND user_id > '.$this->start_user_id;
        $sql .= ' ORDER BY user_id ASC LIMIT '.$this->how_many_users_per_time;
        if( $param == 'test' ){
            $sql = 'SELECT user_id,name,code,enter_date FROM user_info WHERE user_id IN(7119,6932,4462)';
        }
        $res = $this->get_db_rows($sql, $this->db_adapt);//跑job用master，不要用slave
        if( empty( $res ) ){
            return FALSE;
        }
        $this->start_user_id = $res[count($res)-1]['user_id'];
        return $res;
    }


    /**
     * 处理传入的用户数组，清理年假
     * @param array $users    用户数组
     * @param string $start 开始清理年假的日期
     */
    private function do_clear( $users, $start ){
        if( empty( $users ) ){
            return;
        }
        foreach( $users as &$v ){
            $annual_info = $this->get_all_annual( $v );
            if( empty( $annual_info ) ){
                continue;
            }
            //echo "===================\n";print_r($v);print_r( $annual_info );continue;
            if( $annual_info['need_do'] > 0 ){
                $update_success = $this->update_user_info_ext( $v['user_id'], $annual_info['need_do'] );
                usleep(150);
                if( $update_success ){        //更新成功
                    $last_insert_id = $this->insertinto_history_annual( $v, $annual_info['need_do'] );
                    usleep(150);
                }
            }
        }
    }


    /**
     * 更新user_info_ext表
     * @param int $userid    职员id
     * @param int $left_annual    需要清理的年假数
     * @return    boolean        是否清理年假成功
     */
    private function update_user_info_ext( $userid, $left_annual ){
        $ck_sql = "SELECT * FROM user_info_ext WHERE user_id=".$userid;
        $user_data = $this->get_db_row($ck_sql,$this->db_adapt,array());
        if(empty($user_data['user_id'])){
            $in_sql = "INSERT INTO `user_info_txt` (`user_id`, `annual_used`, `annual_total`, `annual_left`, `leave_status`) VALUES ('{$userid}', '{$left_annual}', 0, 0, '0');";
            $this->execute( $in_sql,array(), $this->db_adapt);
            return true;
        }
        $sql  = 'UPDATE user_info_ext SET annual_used = annual_used + '.$left_annual;
        $sql .= ' WHERE user_id = '.$userid;
        $afftectedRows = $this->alter_db_data( $sql, $this->db_adapt );
        if( 0 != $afftectedRows ){    //更新成功
            $this->log('用户ID：'.$userid.' 清理年假 '.$left_annual.' 天成功！');
            return TRUE;
        }else{                              //更新成功
            $this->log('用户ID：'.$userid.' 清理年假 '.$left_annual.' 天失败！');
            return FALSE;
        }
    }


    /**
     * 在history_annual中插入一条数据，以便job失败时可以恢复
     * @param array $user 用户数组
     * @param int $left_annual 需要处理的数据
     */
    private function insertinto_history_annual( &$user, $left_annual ){
        $sql  = 'INSERT INTO history_annual(user_id,code,annual,year)';
        $sql .=' VALUES('.$user['user_id'].',\''.$user['code'].'\','.$left_annual.','.$this->year.')';
        $last_insert_id = $this->execute($sql, array(), $this->db_adapt);
        if( $last_insert_id ){    //插入历史成功
            $this->log('用户ID：'.$user['user_id'].' 插入 history_annual 表 '.$left_annual.'天 '.$this->year.'年 成功！');
            $this->cleared_user .= "\n".$user['name'].'('.$user['user_id'].'  '.$user['code'].' '.$left_annual.'天)';
        }else{                     //插入历史失败
            $this->log('用户ID：'.$user['user_id'].' 插入 history_annual 表 '.$left_annual.'天 '.$this->year.'年 失败！');
        }
        return;
    }


    /**
     * 算出应该清理的年假，copy from 封寒军
     * @param array $userinfo 用户信息
     * @return array $annual 年假信息
     */
    private function get_all_annual( $userinfo ){
        $result = array();
        //如果用户未登录，返回空数组
        if(empty($userinfo['user_id'])) {
            return $result;
        }
        apf_require_class('Tools_Tools');
        apf_require_class('Bll_Attendance_UserExt');
        apf_require_class('Bll_Attendance_HistoryAnnual');
        apf_require_class('Bll_Attendance_LeaveRecord');
        $bll = new Bll_Attendance_UserExt();
        $l_bll = new Bll_Attendance_LeaveRecord();
        $h_bll = new Bll_Attendance_HistoryAnnual();
        $history = $h_bll->get_history_annual_data($userinfo['user_id']);
        $annual['all'] = Tools_Tools::get_instance()->annual($userinfo['enter_date']);
        $annual['used'] = $bll->get_used_annual($userinfo['user_id']);
        $annual['left'] = $annual['all'] - $annual['used'];
        $start = date('Y-m-d',mktime(0,0,0,1,0,date('Y')));;
        $end = date('Y-m-d',mktime(0,0,0,1,0,date('Y')+1));
        //用户当年请假总数
        $i_2 = date('Y') - 1;
        $i_1 = date('Y');
        $twevle = isset($history[$i_2])?$history[$i_2]:0;
        $evlevent = isset($history[$i_1]) ?$history[$i_1]:0;
        $clear_day = $l_bll->get_annual_by_condition($userinfo['user_id'],$start,$end);
        //推算需要清零的假
        $sys = Tools_Tools::get_instance()->clear_annual_to_zero($userinfo['enter_date'],$start);
        $need = 0;
        //2010年的所有年假
        $ten = Tools_Tools::get_instance()->clear_annual_to_zero($userinfo['enter_date'],'2010-12-31 00:00:00');
        if($sys['oneyear_leave_annual']) {
            $need += $sys['oneyear_leave_annual'];
        }
        if($ten['oneyear_leave_annual']) {
            $need += $ten['oneyear_leave_annual'];
        }
        $need = $need  - $clear_day - $twevle - $evlevent;
        if($need < 0) {
            $need = 0;
        }
        //如计算正确无问题后，改用need的数值
        $annual['need_do'] = 0;
        if($need > 0) {
            $annual['need_do'] = $need;//今年还有多少天会过期
        }
        $annual['clear_date'] = date('Y.m.d',mktime(0,0,0,1,0,date('Y')+1));
        return $annual;
    }


    /**
     * foreach实行回滚
     * @param array $users 需要被回滚你的用户
     * @return boolean 回滚是否成功
     */
    private function do_roll_back( $users ){
        if( empty($users) ){
            $this->log('没有需要回滚年假的职员！');die;
        }
        foreach( $users as $v ){
            $affectedRows = $this->roll_back_user_info_ext( $v['user_id'], $v['annual'] );//回滚user_info_ext表
            usleep(150);
            if( 0 != $affectedRows ){
                $this->delete_from_history_annual( $v['user_id'], $v['annual'] );//删除该用户在histoty_annual中的历史
                usleep(150);
            }
        }
        return TRUE;
    }


    /**
     * job执行失败时回滚user_info_ext表的数据
     * @param int $userid 用户id
     * @param int $left_annual 需要回滚几天的年假
     * @return int 数据库被影响的行数
     */
    private function roll_back_user_info_ext( $userid, $left_annual ){
        $sql  = 'UPDATE user_info_ext SET annual_used = annual_used - '.$left_annual;
        $sql .= ' WHERE user_id = '.$userid;
        return $res = $this->alter_db_data($sql, $this->db_adapt);
    }


    /**
     * 回滚成功后从history_annual表中删除已经被回滚的历史记录
     * @param  int $userid 用户id
     * @param int $left_annual 需要回滚的该用户的年假天数
     * @return string
     */
    private  function delete_from_history_annual( $userid, $left_annual ){
        $sql = 'DELETE FROM history_annual WHERE year='.$this->year.' AND user_id='.$userid.' AND annual='.$left_annual;
        return $this->execute( $sql, array(), $this->db_adapt );
    }


    /**
     * 取得上一次已经清理成功的职员，
     * @return array 上次跑job失败时已经清理年假的的职员
     */
    private function get_cleared_user_last_time(){
        $sql = 'SELECT user_id,annual FROM history_annual WHERE year='.$this->year;
        return $users = $this->get_db_rows($sql, $this->db_adapt);
    }
//class end
}
